﻿using System;
using System.Collections.ObjectModel;
using BookSourceVerification.common;
using BookSourceVerification.execute;
using BookSourceVerification.handlers;
using BookSourceVerification.utils;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Win32;
using Newtonsoft.Json;
using NLog;

namespace BookSourceVerification.modelview;

public class VerifyBookSourceViewModel : BaseNotify
{
    private readonly Logger _logger = LogManager.GetCurrentClassLogger();
    public RelayCommand AddFileCommand { get; }
    public RelayCommand<int> DelFileCommand { get; }
    public RelayCommand ClearFileCommand { get; }
    public RelayCommand VerifySourceCommand { get; }

    public RelayCommand<bool> LogCheckCommand { get; }
    public RelayCommand<bool> PingCommand { get; }

    public RelayCommand<bool> DelDupCommand { get; }

    public RelayCommand<int> TimeCommand { get; }

    public ObservableCollection<string> FilePathList { get; set; }

    public static ConsoleLogList<string> ConsoleOutput { get; set; }
    private static readonly VerifyBookSourceExecute _verifyBookSourceExecute = new();

    private bool _allCanDoExecute = true;

    public bool AllCanDoExecute
    {
        get => _allCanDoExecute;
        set => this.SetField(ref _allCanDoExecute, value);
    }


    public VerifyBookSourceViewModel()
    {
        this.FilePathList = new ObservableCollection<string>();
        ConsoleOutput = new ConsoleLogList<string>();
        _verifyBookSourceExecute.ShowCountEvent += VerifyBookSourceExecuteOnShowCountEvent;
        this.DelFileCommand =
            new RelayCommand<int>(DelFileExecute, _ => this.AllCanDoExecute);
        this.ClearFileCommand =
            new RelayCommand(ClearFileExecute, () => this.AllCanDoExecute);
        this.AddFileCommand = new RelayCommand(AddFileDoExecute, () => this.AllCanDoExecute);
        this.VerifySourceCommand = new RelayCommand(VerifySourceExecute, () => this.AllCanDoExecute);
        this.LogCheckCommand = new RelayCommand<bool>(LogCheckExecute, _ => this.AllCanDoExecute);
        this.PingCommand = new RelayCommand<bool>(PingExecute, _ => this.AllCanDoExecute);
        this.DelDupCommand = new RelayCommand<bool>(DelDupExecute, _ => this.AllCanDoExecute);
        this.TimeCommand =
            new RelayCommand<int>(TimeChangeCheckExecute, _ => this.AllCanDoExecute);
        UiConsoleUtils.Log("提示：可以多选书源");
        UiConsoleUtils.Log("也可以拖选多个书源文件到程序界面");
    }

    private void VerifyBookSourceExecuteOnShowCountEvent(int success, int check, long time)
    {
        UiConsoleUtils.Log($"有效：{success}，已测试：{check}，时间：{time} s");
    }

    private void DelDupExecute(bool isChecked)
    {
        var handlerChain = HandlerChainFactory.GetHandlerChain();
        if (isChecked)
        {
            handlerChain.AddHandlerAfter(typeof(DoubtHandler), new DelDoubleHandler());
            // Config.ENABLE_DEL_DUP = true;
            UiConsoleUtils.Log("开启去重");
        }
        else
        {
            // Config.ENABLE_DEL_DUP = false;
            handlerChain.RemoveHandler(typeof(DelDoubleHandler));
            UiConsoleUtils.Log("关闭去重");
        }
    }

    private void TimeChangeCheckExecute(int index)
    {
        Config.TIMEOUT = (index + 1) * 1000;
        var handlerChain = HandlerChainFactory.GetHandlerChain();
        var handler = handlerChain.GetHandler(typeof(HttpVerifyHandler)) as HttpVerifyHandler;
        handler?.SetHttpClientTimeout();
        UiConsoleUtils.Log($"当前超时时间为：{Config.TIMEOUT} 毫秒");
    }

    private void PingExecute(bool isChecked)
    {
        var handlerChain = HandlerChainFactory.GetHandlerChain();
        if (isChecked)
        {
            UiConsoleUtils.Log("开启 Ping 测试模式");
            handlerChain.ReplaceHandler(typeof(HttpVerifyHandler), new PingVerifyHandler());
        }
        else
        {
            UiConsoleUtils.Log("开启 Http 测试模式");
            var handler = handlerChain.ReplaceHandler(typeof(PingVerifyHandler), new HttpVerifyHandler());
            if (handler is PingVerifyHandler h)
            {
                h.PingPool.ShutDown();
            }
        }
    }

    private void LogCheckExecute(bool isChecked)
    {
        if (isChecked)
        {
            LogManager.ResumeLogging();
            UiConsoleUtils.Log("开启日志记录");
        }
        else
        {
            LogManager.SuspendLogging();
            UiConsoleUtils.Log("关闭日志记录");
        }

        LogManager.ReconfigExistingLoggers();
    }


    private async void VerifySourceExecute()
    {
        var fIlePathList = FilePathList;
        try
        {
            this.AllCanDoExecute = false;
            foreach (var path in fIlePathList)
            {
                UiConsoleUtils.Log("============== BEGIN ================");
                UiConsoleUtils.Log($"书源：{path} 开始测试。。。");
                NodeInfoStatistics nodeInfoStatistics;
                try
                {
                    nodeInfoStatistics = await _verifyBookSourceExecute.Execute(path);
                }
                catch (JsonException exception)
                {
                    _logger.Error(exception);
                    UiConsoleUtils.Log($"测试失败！文件JSON格式错误：{exception.Message}");
                    continue;
                }
                catch (Exception e)
                {
                    _logger.Error(e);
                    UiConsoleUtils.Log($"测试失败！发生异常：{e.Message}");
                    continue;
                }

                UiConsoleUtils.Log("测试完成！！！");
                var (availableCount, totalCount, totalTime) = nodeInfoStatistics.StopAndGetAllInfo();
                UiConsoleUtils.Log($"可用：{availableCount}, 已测试：{totalCount}, 时间：{totalTime}秒");
            }
        }
        finally
        {
            this.AllCanDoExecute = true;
            UiConsoleUtils.Log("=============== END =================");
        }
    }


    private void DelFileExecute(int index)
    {
        if (index == -1)
        {
            return;
        }

        FilePathList.RemoveAt(index);
        UiConsoleUtils.Log("删除成功");
    }

    private void ClearFileExecute()
    {
        FilePathList.Clear();
        UiConsoleUtils.Log("清空成功");
    }

    private void AddFileDoExecute()
    {
        var openFileDialog = new OpenFileDialog
        {
            Filter = "文本文件 (*.txt;*.json)|*.txt;*.json",
            Multiselect = true
        };
        if (openFileDialog.ShowDialog() != true) return;
        foreach (var fileName in openFileDialog.FileNames)
        {
            var itemCollection = FilePathList;
            if (itemCollection.Contains(fileName))
            {
                continue;
            }

            FilePathList.Add(fileName);
            UiConsoleUtils.Log("书源添加成功！");
        }
    }
}